﻿///<copyright>
/// Copyright © 2009 Stephen Styrchak. All Rights Reserved.
///</copyright>
using System;
using Microsoft.Xna.Framework;

namespace Ferpect.ComponentModel
{
    /// <summary>
    /// This service manages game pad and keyboard input for a game. It allows a game
    /// to associate each game player with a PlayerIndex (which identifies a game pad).
    /// Games typically initialize the PlayerNNN properties early in the game by having
    /// players press Start on their respective controllers.
    /// </summary>
    [GameService(typeof(IInputService))]
    public class InputService : ControllerComponent, IInputService
    {
        private InputState[] inputStates;
        private Nullable<PlayerIndex> playerOne;
        private Nullable<PlayerIndex> playerTwo;
        private Nullable<PlayerIndex> playerThree;
        private Nullable<PlayerIndex> playerFour;
        private KeyboardInputState keyboard;

        public InputService()
        {
            this.UpdateOrder = Int32.MinValue;
            this.inputStates = new InputState[]
                {
                    new InputState(PlayerIndex.One),
                    new InputState(PlayerIndex.Two),
                    new InputState(PlayerIndex.Three),
                    new InputState(PlayerIndex.Four),
                };
            this.keyboard = new KeyboardInputState();
        }

        public override void Update(Microsoft.Xna.Framework.GameTime gameTime)
        {
            for (int i = 0; i < 4; ++i)
            {
                this.inputStates[i].Update();
            }
            this.keyboard.Update();
        }

        #region IInputService Members

        /// <summary>
        /// Gets/sets the player index of player one. This property must be set explicitly
        /// by the game after determining which PlayerIndex value represents player two.
        /// </summary>
        public Nullable<PlayerIndex> PlayerOne { get { return this.playerOne; } set { this.playerOne = value; } }
        /// <summary>
        /// Gets/sets the player index of player two. This property must be set explicitly
        /// by the game after determining which PlayerIndex value represents player two.
        /// </summary>
        public Nullable<PlayerIndex> PlayerTwo { get { return this.playerTwo; } set { this.playerTwo = value; } }
        /// <summary>
        /// Gets/sets the player index of player three. This property must be set explicitly
        /// by the game after determining which PlayerIndex value represents player three.
        /// </summary>
        public Nullable<PlayerIndex> PlayerThree { get { return this.playerThree; } set { this.playerThree = value; } }
        /// <summary>
        /// Gets/sets the player index of player four. This property must be set explicitly
        /// by the game after determining which PlayerIndex value represents player four.
        /// </summary>
        public Nullable<PlayerIndex> PlayerFour { get { return this.playerFour; } set { this.playerFour = value; } }

        /// <summary>
        /// Gets the input state associated with the specified game pad player index.
        /// </summary>
        /// <param name="playerIndex">The PlayerIndex identifying the game pad to query.</param>
        /// <returns>The InputState instance associated with the specified game pad's PlayerIndex.</returns>
        public InputState GetInputState(PlayerIndex playerIndex)
        {
            return this.inputStates[(int)playerIndex];
        }

        /// <summary>
        /// Gets the system keyboard state. For chat pad keyboards, use the KeyboardInputState
        /// off the player-specific InputState instances.
        /// </summary>
        public KeyboardInputState Keyboard
        {
            get { return this.keyboard; }
        }

        #endregion
    }
}
